/*
题目：袋子里最少数目的球
给你一个整数数组 nums ，其中 nums[i] 表示第 i 个袋子里球的数目。同时给你一个整数 maxOperations 。

你可以进行如下操作至多 maxOperations 次：

    选择任意一个袋子，并将袋子里的球分到 2 个新的袋子中，每个袋子里都有 正整数 个球。
        比方说，一个袋子里有 5 个球，你可以把它们分到两个新袋子里，分别有 1 个和 4 个球，或者分别有 2 个和 3 个球。

你的开销是单个袋子里球数目的 最大值 ，你想要 最小化 开销。

请你返回进行上述操作后的最小开销。
https://leetcode.cn/problems/minimum-limit-of-balls-in-a-bag/description/
 */
public class MinimumSize {
    public int minimumSize(int[] nums, int maxOperations) {
        // 二分答案 时间复杂度：O(nlogn)
        // 题目可以转换成：可以操作 maxOperations 次，求袋子里最少数目的球
        int n = nums.length;
        int left = 1, right = Arrays.stream(nums).max().getAsInt();
        while (left <= right) {
            // 二分答案猜测的袋子里最少数量的球
            int gus = left + ((right - left) >> 1);
            // 然后检验一下是不是
            int ops = 0; // 操作步数
            for (int x : nums) {
                ops += (x - 1) / gus;
            }

            // 如果操作步数还有剩余，那么说明还有继续“操作”的空间，这个数可以再小一点
            if (ops <= maxOperations) {
                right = gus - 1;
            } else {
                left = gus + 1;
            }
        }
        return right + 1;
    }
}
